package yams.task;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import yams.common.constants.InspectionOrderStatusEnum;
import yams.domain.*;
import yams.service.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 定时任务
 * Created by Luffy on 2017/7/28.
 */
@Component
public class ContractAndBillTask {

    private final static Logger logger = LoggerFactory.getLogger(ContractAndBillTask.class);

    @Resource
    private ICheckmeterService checkmeterService;
    @Resource
    private IContractService contractService;
    @Resource
    private IUserInspectionService userInspectionService;
    @Resource
    private IWeChatService weChatService;
    @Resource
    private IEnumService enumService;


    /**
     * 每天凌晨可以做的事情
     * 1. 自动生成房租账单
     * 2. 自动计算下次房租付款日期
     * 3. 检查到期合同更新状态
     * 4. 更新已过预约看房时间的订单
     */
    @Scheduled(cron = "1 1 2 * * ?")
    public void execute() {

        autoGenerateRentBill();
        autoCalcNextPayDate();
        updateContractAndHouseStatus();
        updateUserInspectionStatus();

    }

    /**
     * 自动生成房租账单
     * 在执行合同中，当前时间 < 下次付款日期 < 当前时间+ 数据字典系统配置里的billRemind，自动生成合同账单
     */
    private void autoGenerateRentBill(){

        LocalDate startDate = LocalDate.now();
        //获取单价
        String billRemind = enumService.findByCode("systemConfig").getEnumItemVal("billRemind");
        LocalDate endDate = LocalDate.now().plusDays(Long.valueOf(billRemind));

        logger.info("~~"+startDate.toString()+"自动生成房租账单任务开始~~");
        ContractEntity condition = new ContractEntity();
        condition.getProperties().put("status","1");
        List<ContractEntity> normalContractList = contractService.listAll(condition);

        List<String> resultList = normalContractList.stream()
                .filter(contract -> {
                    String nextPayDateStr = contract.getNextPayDate();
                    if(StringUtils.isEmpty(nextPayDateStr)){
                        return false;
                    }else{
                        LocalDate nextPayDate = LocalDate.parse(nextPayDateStr, DateTimeFormatter.ISO_LOCAL_DATE);
                        if(startDate.compareTo(nextPayDate) < 0 && endDate.compareTo(nextPayDate) > 0){
                            return true;
                        }else{
                            return false;
                        }
                    }
                }).map(contract -> {
                    return contract.getId();
                }).collect(Collectors.toList());

        logger.info("~~本次共生成房租账单"+resultList.size()+"张~~");
        contractService.generateRentBill(resultList);
        logger.info("~~"+startDate.toString()+"自动生成房租账单任务结束~~");

    }

    /**
     * 自动计算下次房租付款日期
     * 执行中的合同，当前日期 = 下次付款日期 ，根据付款周期计算下次付款日期
     */
    private void autoCalcNextPayDate(){

        LocalDate now = LocalDate.now();
        logger.info("~~"+now.toString()+"自动计算下次房租付款日期任务开始~~");
        ContractEntity condition = new ContractEntity();
        condition.getProperties().put("status","1");
        List<ContractEntity> normalContractList = contractService.listAll(condition);

        List<String> resultList = normalContractList.stream()
                .filter(contract -> {
                    String nextPayDateStr = contract.getNextPayDate();
                    if(StringUtils.isEmpty(nextPayDateStr)){
                        return false;
                    }else{
                        LocalDate nextPayDate = LocalDate.parse(nextPayDateStr, DateTimeFormatter.ISO_LOCAL_DATE);
                        if(now.compareTo(nextPayDate) == 0){
                            return true;
                        }else{
                            return false;
                        }
                    }
                }).map(contract -> {
                    return contract.getId();
                }).collect(Collectors.toList());

        logger.info("~~本次任务共计算下次付款日期"+resultList.size()+"次~~");
        for(String id : resultList){
            ContractEntity contract = contractService.findById(id);

            String nextPayDate = "";
            Date startDate = new Date();
            Integer cycle = contract.getPayCycle();
            switch (cycle){
                case 1:
                    nextPayDate = LocalDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault())
                            .plusMonths(1).format(DateTimeFormatter.ISO_LOCAL_DATE);
                    break;
                case 3:
                    nextPayDate = LocalDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault())
                            .plusMonths(3).format(DateTimeFormatter.ISO_LOCAL_DATE);
                    break;
                case 6:
                    nextPayDate = LocalDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault())
                            .plusMonths(6).format(DateTimeFormatter.ISO_LOCAL_DATE);
                    break;
                case 12:
                    nextPayDate = LocalDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault())
                            .plusMonths(12).format(DateTimeFormatter.ISO_LOCAL_DATE);
                    break;
                default:
                    break;
            }
            contract.setNextPayDate(nextPayDate);
            contractService.getRepository().saveEntity(contract);
        }
        logger.info("~~"+now.toString()+"自动计算下次房租付款日期任务结束~~");
    }

    /**
     * 合同到期后需要更新状态
     * 在执行合同中，当前日期 > 合同结束日期，更改合同状态和房屋状态
     */
    private void updateContractAndHouseStatus(){

        LocalDate now = LocalDate.now();
        logger.info("~~"+now.toString()+"自动更新合同到期后状态任务开始~~");
        ContractEntity condition = new ContractEntity();
        condition.getProperties().put("status","1");
        List<ContractEntity> normalContractList = contractService.listAll(condition);

        List<String> resultList = normalContractList.stream()
                .filter(contract -> {
                    Date endDate = contract.getEndDate();
                    if(endDate.compareTo(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())) < 0){
                        return true;
                    }else{
                        return false;
                    }
                }).map(contract -> {
                    return contract.getId();
                }).collect(Collectors.toList());
        logger.info("~~本次任务共结束合同"+resultList.size()+"张~~");
        contractService.finishContracts(resultList);
        logger.info("~~"+now.toString()+"自动更新合同到期后状态任务结束~~");
    }

    /**
     * 预约看房看过后更新状态
     * 在确认过的预约看房中，当前时间 > 预约看房时间 ，更新预约看房订单状态
     */
    private void updateUserInspectionStatus(){

        LocalDate now = LocalDate.now();
        logger.info("~~"+now.toString()+"自动更新预约看房后订单状态任务开始~~");
        UserInspectionEntity condition = new UserInspectionEntity();
        condition.getProperties().put("orderStatus", InspectionOrderStatusEnum.CONFIRM.getValue());
        List<UserInspectionEntity> confirmUserInspnList = userInspectionService.listAll(condition);

        List<String> resultList = confirmUserInspnList.stream()
                .filter(userInspection -> {
                    Date checkRoomDate = userInspection.getCheckRoomDate();
                    if(checkRoomDate.compareTo(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())) < 0){
                        return true;
                    }else{
                        return false;
                    }
                }).map(userInspection -> {
                    return userInspection.getId();
                }).collect(Collectors.toList());

        logger.info("~~本次任务共结束预约看房订单"+resultList.size()+"单~~");
        for(String id : resultList){
            UserInspectionEntity userInspectionEntity = userInspectionService.findById(id);
            userInspectionEntity.setOrderStatus(InspectionOrderStatusEnum.LOOKED.getValue());
            userInspectionService.getRepository().saveEntity(userInspectionEntity);
        }
        logger.info("~~"+now.toString()+"自动更新预约看房后订单状态任务结束~~");
    }

    /**
     * 为了开通红包功能，满足30天都有交易记录的条件，临时生成30笔1毛钱的账单，每天付一笔
     */
    private void test1(){
        logger.info("~~生成30笔账单开始~~");
        checkmeterService.test();
        logger.info("~~生成30笔账单结束~~");
    }

    /**
     * 仅用作测试微信模板消息
     */
    private void test2(){
        logger.info("~~微信消息测试开始~~");
        try {
            WechatTemplateMsg templateMsg = new WechatTemplateMsg();
            templateMsg.setTouser("o10Itw9VllOp3jJIh1lpSyAyS5Zg");
            templateMsg.setTemplate_id("nnkKtkWLzNysX-4M_Zwl5RY40zaRKy4Z1rdYUIFJguI");
            templateMsg.setUrl("");
            TreeMap<String,TreeMap<String,String>> map = Maps.newTreeMap();
//            逾期客户：{{keyword1.DATA}}
//            逾期金额：{{keyword2.DATA}}
//            逾期天数：{{keyword3.DATA}}
            map.put("first", templateMsg.item("这是一条测试消息","#173177"));
            map.put("keyword1", templateMsg.item("罗帆","#173177"));
            map.put("keyword2", templateMsg.item("1元","#173177"));
            map.put("keyword3", templateMsg.item("1天","#173177"));
            map.put("remark", templateMsg.item("若有疑问请与管理员(罗帆13970814647)联系","#173177"));
            templateMsg.setData(map);
            String jsonTempl = JSONObject.toJSONString(templateMsg);
            weChatService.sendTemplate(jsonTempl);
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info("~~微信消息测试结束~~");
    }

}
